package com.kmist.xiakexing.presenters;

import android.util.Log;

import com.kmist.xiakexing.data.IMapDaoCallback;
import com.kmist.xiakexing.data.MapDao;
import com.kmist.xiakexing.interfaces.IMapCallback;
import com.kmist.xiakexing.interfaces.IMapPresenter;
import com.kmist.xiakexing.main.socket.DataRecver;
import com.kmist.xiakexing.main.socket.DataSender;
import com.kmist.xiakexing.main.socket.ISocketCallback;
import com.kmist.xiakexing.main.socket.SockPresenter;
import com.kmist.xiakexing.main.socket.cmd;
import com.kmist.xiakexing.main.socket.retCode;
import com.kmist.xiakexing.utils.MapExitBean;
import com.kmist.xiakexing.utils.MapQyBean;
import com.kmist.xiakexing.utils.scene.MapBean;
import com.kmist.xiakexing.utils.scene.PlayerBean;

import org.json.JSONArray;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MapPresenter implements IMapPresenter, IMapDaoCallback, ISocketCallback {

    private static final String TAG = "MapPresenter";
    private final MapDao mapDao;
    private final SockPresenter sockPresenter;
    private static  MapPresenter sInstance = null;
    private Map<Integer, MapBean> sCache = new HashMap<>();
    private List<IMapCallback> mapCallbacks = new ArrayList<>();

    private final PlayerPresenter playerPresenter;

    public static MapPresenter getmInstance() {
        if (sInstance == null) {
            synchronized (MapPresenter.class){
                sInstance = new MapPresenter();
            }
        }
        return sInstance;
    }


    private MapPresenter(){
        playerPresenter = PlayerPresenter.getInstance();
        sockPresenter = SockPresenter.getInstance();
        sockPresenter.setCallback(this);

        //unused
        mapDao = (MapDao) MapDao.getInstance();
        mapDao.setCallback(this);

        //upplayerlvel 自动升级

    }

    @Override
    public void gotoMap(int newMid) {
        PlayerBean player = playerPresenter.getPlayerd();
        int lastMid = player.getNowmid();
        if(newMid != 0){

            //带测试
            if(player.getNowmid() != newMid){
                //MapBean clmid = getMap(newMid);
                //String playerInfo = player.getUname()+"向"+clmid.getName() +"走去";
                //if(!playerInfo.equals(clmid.getPlayerInfo())){
                //    mapDao.upDatePlayerInfo(lastMid, playerInfo);
                //}
            }
            //待测试
            if(player.getUhp() < 0){
                MapBean retMap = mapDao.getMap(player.getNowmid());
                MapQyBean retQy = mapDao.getQy(retMap.getQy());
            }
            player.setNowmid(newMid);
            playerPresenter.changePlayerSx("nowmid", newMid + "", player.getSid());

            playerPresenter.getPlayer();

        }

        //判断角色是否出现在非法地图 //待测试
        if(player.getNowmid() == 0){
            playerPresenter.changePlayerSx("nowmid", getFirstMid()+"", player.getSid());
            player.setNowmid(getFirstMid());
        }

        getMap(player.getNowmid());
    }

    @Override
    public void getMap(int mid) {
        MapBean map = mapInCache(mid);
        if(map != null){
            onMapLoaded(map);
        }else{
            getMapOnline(mid);
        }
        //if catch return catch
        //else service
        //return mapDao.getMap(mid);
    }

    @Override
    public MapBean getdMap(int mid) {
        return sCache.get(mid);
    }

    private void getMapOnline(int mid) {
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("mid", mid);
            if(mid != 0){
                DataSender info = new DataSender(cmd.CMD_MAP_GETMAP, jsonObject.toString());
                sockPresenter.sendMessage(info.toString());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private MapBean mapInCache(int mid) {
        MapBean map = sCache.get(mid);
        if(map != null)
        {
            Log.d(TAG, "scache have this map");
            return map;
        }else{
            Log.d(TAG, "scache no have this map");
        }

        return null;
    }

    @Override
    public MapQyBean getQy(int qyid) {
        return mapDao.getQy(qyid);
    }

    @Override
    public int getFirstMid() {
        return mapDao.getFirstMid();
    }

    @Override
    public void updateMGTime(int nowmid) {
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("mid", nowmid);
            if(nowmid != 0){
                DataSender info = new DataSender(cmd.CMD_MAP_UPDATEMGTIME, jsonObject.toString());
                sockPresenter.sendMessage(info.toString());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void registerViewCallback(IMapCallback callback) {
        if (!mapCallbacks.contains(callback)){
            mapCallbacks.add(callback);
        }
    }

    @Override
    public void unRegisterViewCallback(IMapCallback callback) {
        mapCallbacks.remove(callback);
    }


    @Override
    public void onMapLoaded(MapBean mapBean) {

        for (IMapCallback callback : mapCallbacks){
            callback.onMapLoaded(mapBean);
        }
    }

    @Override
    public void onMapLoadEmpty() {
        for (IMapCallback callback : mapCallbacks) {
            callback.onMapLoadEmpty();
        }
    }

    @Override
    public void onNetWorkError() {
        for (IMapCallback callback : mapCallbacks) {
            callback.onMapLoadError();
        }
    }

    @Override
    public void onConnected() {

    }

    @Override
    public void onNetworkError() {

    }

    @Override
    public void onDataRecved(DataRecver dataRecver) {
        if (!dataRecver.getResp_cmd().substring(0,2).equals(cmd.CMD_MAP)) {
            return;
        }

        switch (dataRecver.getResp_code()){

            case retCode.RET_OK:{
                if(dataRecver.getResp_cmd().equals(cmd.CMD_MAP_GETMAP)){
                    getMap_handler(dataRecver);
                }else{
                    Log.d("RECV:"," 操作成功！");
                }
            } break;
            default:
                Log.d("RECV:","cmd exe ERROR: "+dataRecver.getResp_code());
            break;

        }
    }

    private void getMap_handler(DataRecver dataRecver) {
        MapBean onlineMap = new MapBean();
        if(parseOnlineMapMsg(dataRecver.getResp_data(), onlineMap)){
            if(!sCache.containsKey(onlineMap.getId())){
                Log.d(TAG, "add sCache");
                sCache.put(onlineMap.getId(), onlineMap);
            }

            for (IMapCallback callback : mapCallbacks) {
                callback.onMapLoaded(onlineMap);
            }
        }else{
            for (IMapCallback callback : mapCallbacks) {
                callback.onMapLoadError();
            }
        }
    }

    private boolean parseOnlineMapMsg(String onlineMap, MapBean map) {
        Log.d(TAG, "onlineMap: "+ onlineMap);
        List<MapExitBean> mapExits = new ArrayList<>();

        try {
            JSONObject jroot = new JSONObject(onlineMap);
            String playerVal = jroot.getString("map");
            JSONObject tmproot = new JSONObject(playerVal);

            map.setId(tmproot.getInt("id"));
            map.setArea(tmproot.getString("area"));
            map.setPname(tmproot.getString("pname"));
            map.setName(tmproot.getString("name"));
            map.setGid(tmproot.getString("gid"));

            try {
                map.setNpc(tmproot.getJSONArray("npc").toString());
            }catch (Exception e){
                map.setNpc("");
            }
            map.setGtime(tmproot.getString("gtime"));
            map.setMs(tmproot.getInt("ms"));
            map.setDesc(tmproot.getString("desc"));
            map.setBoss(tmproot.getString("boss"));
            map.setQy(tmproot.getInt("qy"));
            map.setPlayerInfo(tmproot.getString("playerInfo"));
            map.setIsPvp(tmproot.getInt("isPvp"));

            JSONArray exit = tmproot.getJSONArray("mapExits");
            for(int i =0; i < exit.length(); i++){
                JSONObject value = exit.getJSONObject(i);
                mapExits.add(new MapExitBean(value.getInt("mid"), value.getString("pname"), value.getString("name")));
            }
            map.setMapExits(mapExits);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }
}